﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Utils
{
    public static class IOExtensions
    {
        public static void MakeWritable(this FileInfo file)
        {
            file.Attributes &= (~FileAttributes.ReadOnly);
        }

        public static MemoryStream ToMemory(this byte[] bytes)
        {
            var stream = new MemoryStream(bytes.Length);

            stream.Write(bytes, 0, bytes.Length);
            stream.Seek(0, SeekOrigin.Begin);

            return stream;
        }

        public static MemoryStream ToMemory(this Stream inputream)
        {
            var outputStream = new MemoryStream();

            CopyTo(inputream, outputStream);

            return outputStream;
        }

        public static string ToText(this Stream inputream)
        {
            var bytes = new byte[inputream.Length];

            inputream.Read(bytes, 0, bytes.Length);

            return System.Text.UTF8Encoding.UTF8.GetString(bytes, 0, bytes.Length);
        }

        public static MemoryStream ToStream(this string text)
        {
            var stream = new MemoryStream();
            var bytes = System.Text.UTF8Encoding.UTF8.GetBytes(text);

            stream.Write(bytes, 0, bytes.Length);
            stream.Seek(0, SeekOrigin.Begin);

            return stream;
        }

        public static void CopyTo(this Stream inputream, Stream outputStream)
        {
            var bytes = new byte[inputream.Length];

            inputream.Read(bytes, 0, bytes.Length);
            outputStream.Write(bytes, 0, (int) inputream.Length);

            outputStream.Seek(0, SeekOrigin.Begin);
        }

#if !SILVERLIGHT
        public static string Expand(this string pathLocation)
        {
            return Environment.ExpandEnvironmentVariables(pathLocation);
        }

        public static void ForceDelete(this DirectoryInfo directory)
        {
            foreach (var file in directory.GetFiles())
            {
                if (file.IsReadOnly)
                {
                    file.MakeWritable();
                }

                file.Delete();
            }

            foreach (var subDirectory in directory.GetDirectories())
            {
                subDirectory.ForceDelete();
            }

            try
            {
                directory.Delete();
            }
            catch
            {
                directory = new DirectoryInfo(directory.FullName);

                foreach (var file in directory.GetFiles())
                {
                    if (file.IsReadOnly)
                    {
                        file.MakeWritable();
                    }

                    file.Delete();
                }

                foreach (var subDirectory in directory.GetDirectories())
                {
                    subDirectory.ForceDelete();
                }

                directory.Delete();
            }
        }

        public static bool IsClrImage(string fileName)
        {
            FileStream fs = null;

            try
            {
                fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                byte[] dat = new byte[300];
                fs.Read(dat, 0, 128);
                if ((dat[0] != 0x4d) || (dat[1] != 0x5a)) // "MZ" DOS header 
                    return false;

                int lfanew = BitConverter.ToInt32(dat, 0x3c);
                fs.Seek(lfanew, SeekOrigin.Begin);
                fs.Read(dat, 0, 24); // read signature & PE file header 
                if ((dat[0] != 0x50) || (dat[1] != 0x45)) // "PE" signature 
                    return false;

                fs.Read(dat, 0, 96 + 128); // read PE optional header 
                if ((dat[0] != 0x0b) || (dat[1] != 0x01)) // magic 
                    return false;

                int clihd = BitConverter.ToInt32(dat, 208); // get IMAGE_COR20_HEADER rva-address 
                return clihd != 0;
            }
            catch (Exception)
            {
                return false;
            }
            finally
            {
                if (fs != null)
                    fs.Close();
            }
        } 

#endif
    }
}
